import axios from 'axios'
import { getHttpUrl } from './domain'

const instance = axios.create({
  baseURL: getHttpUrl(),
  headers: {
    Accept: 'text/plain;',
    'Accept-Language': 'zh-CN',
    'Content-Encoding': 'deflate; g-zip',
    'Cache-Control': 'no-cache',
    'Content-Type': 'application/json; charset=UTF-8'
  },
  withCredentials: true
})

// 请求队列
const queue = []

// axios内置的中断请求的方法
const CancelToken = axios.CancelToken

/**
 * 拼接请求的url和方法，同样的url+方法可以视为相同的请求
 * @param config
 * @returns {string}
 */
const token = (config) => {
  return `${config.url}_${config.method}`
}

/**
 * 中断重复的请求，并从队列中移除
 * @param config
 */
const removeQueue = (config) => {
  for (let i = 0, size = queue.length; i < size; i++) {
    const task = queue[i]
    if (task && task.token === token(config)) {
      task.cancel()
      queue.splice(i, 1)
    }
  }
}

/**
 * 请求拦截器
 */
instance.interceptors.request.use(config => {
  // 中断之前的同名请求
  removeQueue(config)
  // 添加cancelToken
  config.cancelToken = new CancelToken((c) => {
    queue.push({ token: token(config), cancel: c })
  })
  return config
}, error => {
  return Promise.reject(error)
})

/**
 * 响应拦截器
 */
instance.interceptors.response.use(response => {
  // 在请求完成后，自动移出队列
  removeQueue(response.config)
  if (response.data === null) {
    return Promise.reject({ errorCode: -1, errorMsg: 'request error' })
  }
  let data = response.data
  if (response.data.Code === 0) {
    data = response.data.Data
  }
  try {
    if (typeof data === 'object') {
      return data
    }
    return JSON.parse(data)
  } catch (e) {
    return data
  }
}, () => { return Promise.reject({ errorCode: -1, errorMsg: 'network error' }) })

/**
 * 取消所有请求
 */
function cancel () {
  for (let i = 0, size = queue.length; i < size; i++) {
    const task = queue[i]
    if (task) {
      task.cancel()
      queue.splice(i, 1)
    }
  }
}

/**
 * 封装后的post方法
 *
 * @param {string} url 请求路径
 * @param {object} data 请求参数
 * @returns
 */
function post (url, data = {}) {
  return instance.post(url, JSON.stringify(data))
}

/**
 * 封装后的get方法
 *
 * @param {string} url 请求路径
 * @param {object} data 请求参数
 * @returns
 */
function get (url, data = {}) {
  const keyValues = []
  Object.keys(data).forEach(key => {
    keyValues.push(`${key}=${data[key]}`)
  })
  const spliceUrl = `${url}?${keyValues.join('&')}`
  return instance.get(spliceUrl)
}

export { cancel, post, get }
